﻿using theeg.GraphWpf.Models;

namespace theeg.GraphWpf.Arrangement
{
    internal static class ThreePointRouting
    {
        internal static void CalculateEndpointOrientation(Transition transition, RoutingConfiguration configuration)
        {
            var source = transition.Source;
            var target = transition.Target;
            var targetOffset1 = configuration.GetOffset(target);
            var sourceOffset1 = configuration.GetOffset(source);
            var targetOffset2 = configuration.GetSecondDimensionOffset(target);
            var sourceOffset2 = configuration.GetSecondDimensionOffset(source);
            var sourceExtent1 = configuration.GetExtent(source);
            var targetExtent1 = configuration.GetExtent(target);
            var sourceExtent2 = configuration.GetSecondDimensionExtent(source);
            var targetExtent2 = configuration.GetSecondDimensionExtent(target);

            if (targetOffset1 <= sourceOffset1 + sourceExtent1 &&
                sourceOffset1 + targetExtent1 / 2 >= sourceOffset1 + sourceExtent1 / 2 ||
                targetOffset1 <= sourceOffset1 &&
                targetOffset1 + targetExtent1 / 2 >= sourceOffset1)
            {
                transition.SourceOrientation = targetOffset2 + targetExtent2 / 2 > sourceOffset2 + sourceExtent2 / 2
                    ? configuration.ConnectorSecondDimensionAlternate : configuration.ConnectorSecondDimensionDefault;
            }
            transition.SourceOrientation = targetOffset1 + targetExtent1 / 2 > sourceOffset1 + sourceExtent1 / 2
                ? configuration.ConnectorDefault : configuration.ConnectorAlternate;

            if (sourceOffset1 <= targetOffset1 + targetExtent1 &&
                sourceOffset1 + sourceExtent1 >= targetOffset1 + targetExtent1 ||
                sourceOffset1 <= targetOffset1 &&
                sourceOffset1 + sourceExtent1 >= targetOffset1)
            {
                transition.TargetOrientation = sourceOffset2 + sourceExtent2 / 2 > targetOffset2 + targetExtent2 / 2
                    ? configuration.ConnectorSecondDimensionAlternate : configuration.ConnectorSecondDimensionDefault;
            }
            transition.TargetOrientation = sourceOffset1 + sourceExtent1 / 2 > targetOffset1 + targetExtent1 / 2
                ? configuration.ConnectorDefault : configuration.ConnectorAlternate;
            transition.RoutingPoints.Add(RoutingMediator.OrientationToEndpoint(transition.SourceOrientation, transition.Source));
            transition.RoutingPoints.Add(RoutingMediator.OrientationToEndpoint(transition.TargetOrientation, transition.Target));
        }

        internal static void CalculateRoutingPoints(Transition transition, RoutingConfiguration configuration)
        {
            transition.RoutingPoints.Clear();
            CalculateEndpointOrientation(transition, configuration);
            var source = transition.Source;
            var target = transition.Target;
            int index = 1;

            var sourceIsFirstDimension = (transition.SourceOrientation == configuration.ConnectorAlternate || transition.SourceOrientation == configuration.ConnectorDefault);
            var targetIsFirstDimension = (transition.TargetOrientation == configuration.ConnectorAlternate || transition.TargetOrientation == configuration.ConnectorDefault);
            if (sourceIsFirstDimension && targetIsFirstDimension)
            {
                transition.RoutingPoints.Insert(index++, configuration.CreateIntermediatePoint3((configuration.GetOffset(target) + configuration.GetOffset(source)) / 2, configuration.GetSecondDimensionOffset(source)));
                transition.RoutingPoints.Insert(index, configuration.CreateIntermediatePoint3((configuration.GetOffset(target) + configuration.GetOffset(source)) / 2, configuration.GetSecondDimensionOffset(target)));
            }
            else if (!sourceIsFirstDimension && !targetIsFirstDimension)
            {
                transition.RoutingPoints.Insert(index++, configuration.CreateIntermediatePoint3(configuration.GetOffset(source), (configuration.GetSecondDimensionOffset(target) + configuration.GetSecondDimensionOffset(source)) / 2));
                transition.RoutingPoints.Insert(index, configuration.CreateIntermediatePoint3(configuration.GetOffset(target), (configuration.GetSecondDimensionOffset(target) + configuration.GetSecondDimensionOffset(source)) / 2));
            }
            else if (sourceIsFirstDimension && !targetIsFirstDimension)
            {
                transition.RoutingPoints.Insert(index, configuration.CreateIntermediatePoint3(configuration.GetOffset(target), configuration.GetSecondDimensionOffset(source)));
            }
            else
            {
                transition.RoutingPoints.Insert(index, configuration.CreateIntermediatePoint3(configuration.GetOffset(source), configuration.GetSecondDimensionOffset(target)));
            }
        }
    }
}
